package com.google.code.gronono.gps.ui.panels.pages;

import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.FocusAdapter;
import java.awt.event.FocusEvent;
import java.awt.event.ItemEvent;
import java.awt.event.ItemListener;
import java.io.File;
import java.text.DateFormat;
import java.text.MessageFormat;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.Map;

import javax.swing.ButtonGroup;
import javax.swing.GroupLayout;
import javax.swing.JButton;
import javax.swing.JCheckBox;
import javax.swing.JLabel;
import javax.swing.JOptionPane;
import javax.swing.JRadioButton;
import javax.swing.JScrollPane;
import javax.swing.JTextArea;
import javax.swing.JTextField;
import javax.swing.GroupLayout.Alignment;
import javax.swing.LayoutStyle.ComponentPlacement;
import javax.swing.event.DocumentEvent;

import org.apache.commons.lang.StringUtils;

import com.google.code.gronono.commons.io.file.FileUtils;
import com.google.code.gronono.commons.swing.SwingUtils;
import com.google.code.gronono.commons.swing.listeners.ModifyListener;
import com.google.code.gronono.gps.model.Configuration;
import com.google.code.gronono.gps.model.enums.FilterDateType;
import com.google.code.gronono.gps.model.enums.FilterType;
import com.google.code.gronono.gps.model.enums.PatternType;
import com.google.code.gronono.gps.model.enums.ProcessAction;
import com.google.code.gronono.gps.pattern.KeywordsPattern;
import com.google.code.gronono.gps.pattern.SupportedPatternElement;
import com.google.code.gronono.gps.ui.GPSFrame;
import com.google.code.gronono.gps.ui.controller.GPSController;
import com.google.code.gronono.gps.ui.controller.actions.BrowseAction;

import fr.gronono.gbundle.Bundle;

/**
 * Page affichant des options avancées.
 *
 * @author gael.lorent-fonfrede
 */
@Bundle("com.google.code.gronono.gps.gui")
public class AdvancedOptionsPanel extends AbstractPagePanel {
	/** serialVersionUID. */
	private static final long serialVersionUID = 7217767664141548286L;

	/** Label du traitement des fichiers. */
	@Bundle("options.page.process.action.lbl")
	private static String PROCESS_ACTION_LBL;
	/** Label du radio copier. */
	@Bundle("options.page.copy.lbl")
	private static String COPY_LBL;
	/** Label du radio déplacer. */
	@Bundle("options.page.move.lbl")
	private static String MOVE_LBL;

	/** Label de la checkbox écraser. */
	@Bundle("options.page.overwrite.lbl")
	private static String OVERWRITE_LBL;
	/** Tooltip de la checkbox écraser. */
	@Bundle("options.page.overwrite.tooltip")
	private static String OVERWRITE_TOOLTIP;
	/** Label de la checkbox récursif. */
	@Bundle("options.page.recursive.lbl")
	private static String RECURSIVE_LBL;
	/** Tooltip de la checkbox écraser. */
	@Bundle("options.page.recursive.tooltip")
	private static String RECURSIVE_TOOLTIP;
	/** Label de la checkbox redresser. */
	@Bundle("options.page.rotate.lbl")
	private static String ROTATE_LBL;
	/** Tooltip de la checkbox écraser. */
	@Bundle("options.page.rotate.tooltip")
	private static String ROTATE_TOOLTIP;

	/** Label du type de filtre. */
	@Bundle("options.page.filter.type.lbl")
	private static String FILTER_TYPE_LBL;
	/** Label du type de filtre par extension. */
	@Bundle("options.page.filter.type.extension.lbl")
	private static String FILTER_TYPE_EXTENSION_LBL;
	/** Label du type de filtre par expression. */
	@Bundle("options.page.filter.type.expression.lbl")
	private static String FILTER_TYPE_EXPRESSION_LBL;
	/** Tooltip du type de filtre par expression. */
	@Bundle("options.page.filter.type.expression.tooltip")
	private static String FILTER_TYPE_EXPRESSION_TOOLTIP;

	/** Label du filtre par extension. */
	@Bundle("options.page.filter.extension.lbl")
	private static String FILTER_EXTENSION_LBL;
	/** Tooltip du filtre par extension. */
	@Bundle("options.page.filter.extension.tooltip")
	private static String FILTER_EXTENSION_TOOLTIP;
	/** Titre du message d'erreur de validation du filtre par extension. */
	@Bundle("options.page.filter.extension.err.title")
	private static String FILTER_EXTENSION_ERR_TITLE;
	/** Message d'erreur de validation du filtre par extension. */
	@Bundle("options.page.filter.extension.err.msg")
	private static String FILTER_EXTENSION_ERR_MSG;

	/** Label du filtre par expression régulière. */
	@Bundle("options.page.filter.expression.lbl")
	private static String FILTER_EXPRESSION_LBL;
	/** Tooltip du filtre par expression régulière. */
	@Bundle("options.page.filter.expression.tooltip")
	private static String FILTER_EXPRESSION_TOOLTIP;

	/** Label de l'affichage des rejets du filtre. */
	@Bundle("options.page.filter.show.rejects.lbl")
	private static String FILTER_SHOW_REJECTS_LBL;
	/** Tooltip de l'affichage des rejets du filtre. */
	@Bundle("options.page.filter.show.rejects.tooltip")
	private static String FILTER_SHOW_REJECTS_TOOLTIP;

	/** Label du filtre par date. */
	@Bundle("options.page.filter.by.date.lbl")
	private static String FILTER_BY_DATE_LBL;
	/** Label de la checkbox d'activation du filtre par date. */
	@Bundle("options.page.filter.by.date.btn.lbl")
	private static String FILTER_BY_DATE_BTN_LBL;
	/** Label de la date de début. */
	@Bundle("options.page.filter.date.min.lbl")
	private static String FILTER_DATE_MIN_LBL;
	/** Tooltip de la date de début. */
	@Bundle("options.page.filter.date.min.tooltip")
	private static String FILTER_DATE_MIN_TOOLTIP;
	/** Titre du message d'erreur de validation de la date de début. */
	@Bundle("options.page.filter.date.min.err.title")
	private static String FILTER_DATE_MIN_ERR_TITLE;
	/** Message d'erreur de validation de la date de début. */
	@Bundle("options.page.filter.date.min.err.msg")
	private static String FILTER_DATE_MIN_ERR_MSG;
	/** Label de la date de fin. */
	@Bundle("options.page.filter.date.max.lbl")
	private static String FILTER_DATE_MAX_LBL;
	/** Tooltip de la date de fin. */
	@Bundle("options.page.filter.date.max.tooltip")
	private static String FILTER_DATE_MAX_TOOLTIP;
	/** Titre du message d'erreur de validation de la date de fin. */
	@Bundle("options.page.filter.date.max.err.title")
	private static String FILTER_DATE_MAX_ERR_TITLE;
	/** Message d'erreur de validation de la date de fin. */
	@Bundle("options.page.filter.date.max.err.msg")
	private static String FILTER_DATE_MAX_ERR_MSG;
	/** Label du format de date. */
	@Bundle("options.page.filter.date.format.lbl")
	private static String FILTER_DATE_FORMAT_LBL;
	/** Tooltip du format de date. */
	@Bundle("options.page.filter.date.format.tooltip")
	private static String FILTER_DATE_FORMAT_TOOLTIP;
	/** Titre du message d'erreur de validation du format de date. */
	@Bundle("options.page.filter.date.format.err.title")
	private static String FILTER_DATE_FORMAT_ERR_TITLE;
	/** Message d'erreur de validation du format de date. */
	@Bundle("options.page.filter.date.format.err.msg.start")
	private static String FILTER_DATE_FORMAT_ERR_MSG_START;
	/** Message d'erreur de validation du format de date. */
	@Bundle("options.page.filter.date.format.err.msg.ok")
	private static String FILTER_DATE_FORMAT_ERR_MSG_OK;
	/** Message d'erreur de validation du format de date. */
	@Bundle("options.page.filter.date.format.err.msg.ko")
	private static String FILTER_DATE_FORMAT_ERR_MSG_KO;
	/** Message d'erreur de validation du format de date. */
	@Bundle("options.page.filter.date.format.err.msg.end")
	private static String FILTER_DATE_FORMAT_ERR_MSG_END;
	/** Label du type de date. */
	@Bundle("options.page.filter.date.type.lbl")
	private static String FILTER_DATE_TYPE_LBL;
	/** Label du type de date exif. */
	@Bundle("options.page.filter.date.type.exif.btn.lbl")
	private static String FILTER_DATE_TYPE_EXIF_LBL;
	/** Tooltip du type de date exif. */
	@Bundle("options.page.filter.date.type.exif.btn.tooltip")
	private static String FILTER_DATE_TYPE_EXIF_TOOLTIP;
	/** Label du type de date lastmod. */
	@Bundle("options.page.filter.date.type.lastmod.btn.lbl")
	private static String FILTER_DATE_TYPE_LASTMOD_LBL;
	/** Tooltip du type de date lastmod. */
	@Bundle("options.page.filter.date.type.lastmod.btn.tooltip")
	private static String FILTER_DATE_TYPE_LASTMOD_TOOLTIP;

	/** Label du type de pattern. */
	@Bundle("options.page.pattern.type.lbl")
	private static String PATTERN_TYPE_LBL;
	/** Label du type de pattern js. */
	@Bundle("options.page.pattern.type.js.lbl")
	private static String PATTERN_TYPE_JS_LBL;
	/** Tooltip du type de pattern js. */
	@Bundle("options.page.pattern.type.js.tooltip")
	private static String PATTERN_TYPE_JS_TOOLTIP;
	/** Label du type de pattern par mots-clés. */
	@Bundle("options.page.pattern.type.keywords.lbl")
	private static String PATTERN_TYPE_KEYWORDS_LBL;

	/** Label du pattern par mots-clés. */
	@Bundle("options.page.pattern.keywords.expression.lbl")
	private static String PATTERN_EXPRESSION_KEYWORDS_LBL;
	/** Tooltip du pattern par mots-clés. */
	@Bundle("options.page.pattern.keywords.expression.tooltip.start")
	private static String PATTERN_EXPRESSION_KEYWORDS_TOOLTIP_START;
	/** Tooltip du pattern par mots-clés. */
	@Bundle("options.page.pattern.keywords.expression.tooltip.table.open")
	private static String PATTERN_EXPRESSION_KEYWORDS_TOOLTIP_TABLE_OPEN;
	/** Tooltip du pattern par mots-clés. */
	@Bundle("options.page.pattern.keywords.expression.tooltip.row.open")
	private static String PATTERN_EXPRESSION_KEYWORDS_TOOLTIP_ROW_OPEN;
	/** Tooltip du pattern par mots-clés. */
	@Bundle("options.page.pattern.keywords.expression.tooltip.row.between.cells")
	private static String PATTERN_EXPRESSION_KEYWORDS_TOOLTIP_ROW_BETWEEN_CELLS;
	/** Tooltip du pattern par mots-clés. */
	@Bundle("options.page.pattern.keywords.expression.tooltip.row.close")
	private static String PATTERN_EXPRESSION_KEYWORDS_TOOLTIP_ROW_CLOSE;
	/** Tooltip du pattern par mots-clés. */
	@Bundle("options.page.pattern.keywords.expression.tooltip.table.close")
	private static String PATTERN_EXPRESSION_KEYWORDS_TOOLTIP_TABLE_CLOSE;
	/** Tooltip du pattern par mots-clés. */
	@Bundle("options.page.pattern.keywords.expression.tooltip.end")
	private static String PATTERN_EXPRESSION_KEYWORDS_TOOLTIP_END;
	/** Titre du message d'erreur de validation du pattern par mots-clés. */
	@Bundle("options.page.pattern.keywords.expression.err.title")
	private static String PATTERN_EXPRESSION_KEYWORDS_ERR_TITLE;
	/** Message d'erreur de validation du pattern par mots-clés. */
	@Bundle("options.page.pattern.keywords.expression.err.msg")
	private static String PATTERN_EXPRESSION_KEYWORDS_ERR_MSG;

	/** Label du pattern js. */
	@Bundle("options.page.pattern.js.expression.lbl")
	private static String PATTERN_EXPRESSION_JS_LBL;
	/** Tooltip du pattern js. */
	@Bundle("options.page.pattern.js.expression.tooltip")
	private static String PATTERN_EXPRESSION_JS_TOOLTIP;
	/** Largeur d'une zone de texte. */
	@Bundle("options.page.text.field.width")
	private static int TEXT_FIELD_WIDTH;
	/** Hauteur d'une zone de texte. */
	@Bundle("options.page.text.area.height")
	private static int TEXT_AREA_HEIGHT;

	/** Label du traitement des rejet. */
	@Bundle("options.page.reject.process.lbl")
	private static String REJ_PROCESS_LBL;
	/** Label de la checkbox d'activation du traitement des rejet. */
	@Bundle("options.page.reject.process.btn.lbl")
	private static String REJ_PROCESS_BTN_LBL;
	/** Label du dossier de rejet. */
	@Bundle("options.page.reject.dir.lbl")
	private static String REJ_DIR_LBL;
	/** Titre du message d'erreur sur la validation du dossier. */
	@Bundle("options.page.reject.dir.err.title")
	private static String REJ_DIR_ERR_TITLE;
	/** Message d'erreur sur la validation du dossier. */
	@Bundle("options.page.reject.dir.err.msg")
	private static String REJ_DIR_ERR_MSG;
	/** Message d'erreur sur la validation du dossier. */
	@Bundle("options.page.reject.dir.err.msg.notfound")
	private static String REJ_DIR_ERR_MSG_NOTFOUND;
	/** Label du pattern de rejet. */
	@Bundle("options.page.reject.pattern.keywords.expression.lbl")
	private static String REJ_PATTERN_EXPRESSION_KEYWORDS_LBL;

	/** Exception action non-supportée. */
	@Bundle("options.page.init.values.unsupported.process.action")
	private static String UNSUPPORTED_PROCESS_ACTION;
	/** Exception type de filtre non-supporté. */
	@Bundle("options.page.init.values.unsupported.filter.type")
	private static String UNSUPPORTED_FILTER_TYPE;
	/** Exception type de filtre de date non-supporté. */
	@Bundle("options.page.init.values.unsupported.datefilter.type")
	private static String UNSUPPORTED_DATEFILTER_TYPE;
	/** Exception type de pattern non-supporté. */
	@Bundle("options.page.init.values.unsupported.pattern.type")
	private static String UNSUPPORTED_PATTERN_TYPE;

	/** Label du type de traitement. */
	private JLabel actionLbl;
	/** Bouton radio type de traitement copier. */
    private JRadioButton copyBtn;
    /** Bouton radiotype de traitement  déplacer. */
    private JRadioButton moveBtn;

    /** La checkbox écraser. */
    private JCheckBox overwriteBtn;
    /** La checkbox recursif. */
    private JCheckBox recursiveBtn;
    /** La checkbox redresser. */
    private JCheckBox rotateBtn;

    /** Label du type filtre des fichiers. */
    private JLabel filterTypeLbl;
	/** Bouton radio filtre par extension. */
    private JRadioButton filterTypeExtensionBtn;
    /** Bouton radio filtre par expression. */
    private JRadioButton filterTypeExpressionBtn;

    /** La checkbox afficher fichiers filtrés. */
    private JCheckBox filterShowRejectsBtn;

    /** Label du filtre par extension. */
    private JLabel filterExtensionLbl;
    /** Champ de saisie du filtre par extension. */
    private JTextField filterExtensionTxt;

    /** Label du filtre par expression. */
    private JLabel filterExpressionLbl;
    /** Champ de saisie du filtre par expression. */
    private JTextField filterExpressionTxt;

    /** Label filtrer par date. */
    private JLabel filterByDateLbl;
    /** La checkbox filtrer par date. */
    private JCheckBox filterByDateBtn;
    /** Label date min filtre .*/
    private JLabel filterDateMinLbl;
    /** Champ de saisie de la date min pour le filtre. */
    private JTextField filterDateMinTxt;
    /** Label date max filtre. */
    private JLabel filterDateMaxLbl;
    /** Champ de saisie de la date min pour le filtre. */
    private JTextField filterDateMaxTxt;
    /** Label format de date. */
    private JLabel filterDateFormatLbl;
    /** Champ de saisie du format de date. */
    private JTextField filterDateFormatTxt;
    /** Label type de date. */
    private JLabel filterDateTypeLbl;
	/** Le bouton radio type de date exif. */
    private JRadioButton filterDateTypeExifBtn;
    /** Le bouton radio type de date lastmod. */
    private JRadioButton filterDateTypeLastModBtn;

    /** Label du type de pattern. */
	private JLabel patternTypeLbl;
	/** Bouton radio pattern par mots-clés. */
    private JRadioButton patternTypeKeywordsBtn;
    /** Bouton radio pattern js. */
    private JRadioButton patternTypeJsBtn;

    /** Label du pattern par mots-clés. */
    private JLabel patternExpressionKeywordsLbl;
    /** Champ de saisie du pattern par mots-clés. */
    private JTextField patternExpressionKeywordsTxt;

    /** Label du pattern js. */
    private JLabel patternExpressionJsLbl;
    /** Zone de saisie du pattern js. */
    private JTextArea patternExpressionJsTxt;
    /** ScrollPane affichant la zone de saisie. */
	private JScrollPane scrollPane;

	/** Label du traitement des rejets. */
    private JLabel rejectProcessLbl;
	/** Checkbox traiter les rejets. */
	private JCheckBox rejectProcessBtn;
	/** Label du dossier des rejets. */
    private JLabel rejectDirLbl;
    /** Champ de saisie du dossier des rejets. */
    private JTextField rejectDirTxt;
    /** Bouton de parcours du dossier de rejet. */
    private JButton rejectDirBrowseBtn;
    /** Label du pattern de rejet. */
    private JLabel rejectPatternExpressionKeywordsLbl;
    /** Champ de saisie du pattern de rejet. */
    private JTextField rejectPatternExpressionKeywordsTxt;

    /** La configuration de l'application. */
    private final Configuration configuration;
    /** La frame principale de l'application. */
    private final GPSFrame gpsFrame;

	/**
	 * Construit la page.
	 * @param controller Le contrôleur de l'application.
	 */
    public AdvancedOptionsPanel(final GPSController controller) {
    	super(controller, null, null);
		this.configuration = controller.getConfiguration();
		this.gpsFrame = controller.getGPSFrame();

		initComponents();
        placeComponents();

        initValues();
    }

	/**
     * Initialise les différents composants.
     */
	private void initComponents() {
        actionLbl = new JLabel(PROCESS_ACTION_LBL);
        moveBtn = new JRadioButton(MOVE_LBL);
        moveBtn.addActionListener(new ActionListener() {
			public void actionPerformed(final ActionEvent e) {
				configuration.setProcessAction(ProcessAction.MOVE);
			}
        });
        copyBtn = new JRadioButton(COPY_LBL);
        copyBtn.addActionListener(new ActionListener() {
			public void actionPerformed(final ActionEvent e) {
				configuration.setProcessAction(ProcessAction.COPY);
			}
        });
        final ButtonGroup actionGroup = new ButtonGroup();
        actionGroup.add(moveBtn);
        actionGroup.add(copyBtn);

        overwriteBtn = new JCheckBox(OVERWRITE_LBL);
        overwriteBtn.setToolTipText(OVERWRITE_TOOLTIP);
        overwriteBtn.addItemListener(new ItemListener() {
        	public void itemStateChanged(final ItemEvent e) {
        		if (e.getStateChange() == ItemEvent.SELECTED) {
        			configuration.setOverwrite(true);
        		} else if (e.getStateChange() == ItemEvent.DESELECTED) {
        			configuration.setOverwrite(false);
        		}
			}
        });

        recursiveBtn = new JCheckBox(RECURSIVE_LBL);
        recursiveBtn.setToolTipText(RECURSIVE_TOOLTIP);
        recursiveBtn.addItemListener(new ItemListener() {
        	public void itemStateChanged(final ItemEvent e) {
        		if (e.getStateChange() == ItemEvent.SELECTED) {
        			configuration.setRecursive(true);
        		} else if (e.getStateChange() == ItemEvent.DESELECTED) {
        			configuration.setRecursive(false);
        		}
			}
        });

        rotateBtn = new JCheckBox(ROTATE_LBL);
        rotateBtn.setToolTipText(ROTATE_TOOLTIP);
        rotateBtn.addItemListener(new ItemListener() {
        	public void itemStateChanged(final ItemEvent e) {
        		if (e.getStateChange() == ItemEvent.SELECTED) {
        			configuration.setRotate(true);
        		} else if (e.getStateChange() == ItemEvent.DESELECTED) {
        			configuration.setRotate(false);
        		}
			}
        });

        filterTypeLbl = new JLabel(FILTER_TYPE_LBL);
        filterTypeExtensionBtn = new JRadioButton(FILTER_TYPE_EXTENSION_LBL);
        filterTypeExtensionBtn.addActionListener(new ActionListener() {
			public void actionPerformed(final ActionEvent e) {
				configuration.setFilterType(FilterType.EXTENSION);
				setFilterVisible(FilterType.EXTENSION);
			}
        });
        filterTypeExpressionBtn = new JRadioButton(FILTER_TYPE_EXPRESSION_LBL);
        filterTypeExpressionBtn.setToolTipText(FILTER_TYPE_EXPRESSION_TOOLTIP);
        filterTypeExpressionBtn.addActionListener(new ActionListener() {
			public void actionPerformed(final ActionEvent e) {
				configuration.setFilterType(FilterType.REGEX);
				setFilterVisible(FilterType.REGEX);
			}
        });
        final ButtonGroup filterTypeGroup = new ButtonGroup();
        filterTypeGroup.add(filterTypeExtensionBtn);
        filterTypeGroup.add(filterTypeExpressionBtn);

        filterExtensionLbl = new JLabel(FILTER_EXTENSION_LBL);
        filterExtensionTxt = new JTextField();
        filterExtensionTxt.setToolTipText(FILTER_EXTENSION_TOOLTIP);
        filterExtensionTxt.addFocusListener(new FocusAdapter() {
			@Override
			public void focusLost(final FocusEvent arg0) {
				final String filterExtension = StringUtils.trimToEmpty(filterExtensionTxt.getText());
				// Rmq ne traite pas exactement tous les cas (par exemple "jpeg, jpg;") mais balaie une majorité d'erreurs simples
				if ((StringUtils.isBlank(filterExtension) || "*".equals(filterExtension)
						|| ((StringUtils.isNotBlank(filterExtension)
								&& (StringUtils.isAlphanumericSpace(filterExtension))) || StringUtils.contains(filterExtension, ',') || StringUtils.contains(filterExtension, '.')))) {
					configuration.setFilterExtension(filterExtension);
				} else {
					configuration.setFilterExtension("");
					JOptionPane.showMessageDialog(gpsFrame, FILTER_EXTENSION_ERR_MSG, FILTER_EXTENSION_ERR_TITLE, JOptionPane.ERROR_MESSAGE);
				}
			}
        });

        filterExpressionLbl = new JLabel(FILTER_EXPRESSION_LBL);
        filterExpressionTxt = new JTextField();
        filterExpressionTxt.setToolTipText(FILTER_EXPRESSION_TOOLTIP);
        // Rmq : pas de validation du la RegEx en onFocusLost : mode avancé
        filterExpressionTxt.getDocument().addDocumentListener(new ModifyListener() {
			@Override
			public void modify(final DocumentEvent event) {
				configuration.setFilterExpression(StringUtils.trimToEmpty(filterExpressionTxt.getText()));
			}
        });

        filterShowRejectsBtn = new JCheckBox(FILTER_SHOW_REJECTS_LBL);
        filterShowRejectsBtn.setToolTipText(FILTER_SHOW_REJECTS_TOOLTIP);
        filterShowRejectsBtn.addItemListener(new ItemListener() {
        	public void itemStateChanged(final ItemEvent e) {
        		if (e.getStateChange() == ItemEvent.SELECTED) {
        			configuration.setFilterShowRejects(true);
        		} else if (e.getStateChange() == ItemEvent.DESELECTED) {
        			configuration.setFilterShowRejects(false);
        		}
			}
        });

        filterByDateLbl = new JLabel(FILTER_BY_DATE_LBL);

        filterByDateBtn = new JCheckBox(FILTER_BY_DATE_BTN_LBL);
        filterByDateBtn.addItemListener(new ItemListener() {
        	public void itemStateChanged(final ItemEvent e) {
        		if (e.getStateChange() == ItemEvent.SELECTED) {
        			configuration.setFilterByDate(true);
        			activateDateFilter(true);
        		} else if (e.getStateChange() == ItemEvent.DESELECTED) {
        			configuration.setFilterByDate(false);
        			activateDateFilter(false);
        		}
			}
        });

        filterDateMinLbl = new JLabel(FILTER_DATE_MIN_LBL);
        filterDateMinTxt = new JTextField();
        filterDateMinTxt.setToolTipText(FILTER_DATE_MIN_TOOLTIP);
        filterDateMinTxt.addFocusListener(new FocusAdapter() {
			@Override
			public void focusGained(final FocusEvent arg0) {
				filterDateMinTxt.selectAll();
			}

			@Override
			public void focusLost(final FocusEvent arg0) {
				filterDateMinTxt.select(0, 0);
				// Validation de la date / au format
				final String dateTxt = StringUtils.trimToEmpty(filterDateMinTxt.getText());
				final String dateFormatTxt = StringUtils.trimToEmpty(filterDateFormatTxt.getText());
				if (StringUtils.isNotBlank(dateTxt) && StringUtils.isNotBlank(dateFormatTxt)) {
					try {
						final DateFormat df = new SimpleDateFormat(dateFormatTxt);
						df.parse(dateTxt);
						configuration.setFilterDateMin(dateTxt);
					} catch (final Throwable t) {
						configuration.setFilterDateMin("");
						final StringBuilder msg = new StringBuilder(MessageFormat.format(FILTER_DATE_MIN_ERR_MSG, dateTxt)).append("\n").append(t.getMessage());
						JOptionPane.showMessageDialog(gpsFrame, msg.toString(), FILTER_DATE_MIN_ERR_TITLE, JOptionPane.ERROR_MESSAGE);
					}
				} else {
					configuration.setFilterDateMin("");
				}
			}
        });

        filterDateMaxLbl = new JLabel(FILTER_DATE_MAX_LBL);
        filterDateMaxTxt = new JTextField();
        filterDateMaxTxt.setToolTipText(FILTER_DATE_MAX_TOOLTIP);
        filterDateMaxTxt.addFocusListener(new FocusAdapter() {
			@Override
			public void focusGained(final FocusEvent arg0) {
				filterDateMaxTxt.selectAll();
			}

			@Override
			public void focusLost(final FocusEvent arg0) {
				filterDateMaxTxt.select(0, 0);
				// Validation de la date / au format
				final String dateTxt = StringUtils.trimToEmpty(filterDateMaxTxt.getText());
				final String dateFormatTxt = StringUtils.trimToEmpty(filterDateFormatTxt.getText());
				if (StringUtils.isNotBlank(dateTxt) && StringUtils.isNotBlank(dateFormatTxt)) {
					try {
						final DateFormat df = new SimpleDateFormat(dateFormatTxt);
						df.parse(dateTxt);
						configuration.setFilterDateMax(dateTxt);
					} catch (final Throwable t) {
						configuration.setFilterDateMax("");
						final StringBuilder msg = new StringBuilder(MessageFormat.format(FILTER_DATE_MAX_ERR_MSG, dateTxt)).append("\n").append(t.getMessage());
						JOptionPane.showMessageDialog(gpsFrame, msg.toString(), FILTER_DATE_MAX_ERR_TITLE, JOptionPane.ERROR_MESSAGE);
					}
				} else {
					configuration.setFilterDateMax("");
				}
			}
        });

        filterDateFormatLbl = new JLabel(FILTER_DATE_FORMAT_LBL);
        filterDateFormatTxt = new JTextField();
        filterDateFormatTxt.setToolTipText(FILTER_DATE_FORMAT_TOOLTIP);
        filterDateFormatTxt.addFocusListener(new FocusAdapter() {
			@Override
			public void focusGained(final FocusEvent arg0) {
				filterDateFormatTxt.selectAll();
			}

			@Override
			public void focusLost(final FocusEvent arg0) {
				filterDateFormatTxt.select(0, 0);
				// Validation/aperç du format de date
				final String dateFormatTxt = StringUtils.trimToEmpty(filterDateFormatTxt.getText());
				if (StringUtils.isNotBlank(dateFormatTxt)) {
					final StringBuilder msg = new StringBuilder(FILTER_DATE_FORMAT_ERR_MSG_START);
					final StringBuilder msg2 = new StringBuilder();
					try {
						final DateFormat df = new SimpleDateFormat(dateFormatTxt);
						final String preview = df.format(new Date());
						msg2.append(FILTER_DATE_FORMAT_ERR_MSG_OK).append(preview);
						configuration.setFilterDateFormat(dateFormatTxt);
					} catch (final Throwable t) {
						configuration.setFilterDateFormat("");
						msg2.append(MessageFormat.format(FILTER_DATE_FORMAT_ERR_MSG_KO, dateFormatTxt)).append("\n").append(t.getMessage());
						JOptionPane.showMessageDialog(gpsFrame, msg2.toString(), FILTER_DATE_FORMAT_ERR_TITLE, JOptionPane.ERROR_MESSAGE);
					}
					msg.append(msg2);
					msg.append(FILTER_DATE_FORMAT_ERR_MSG_END);
					filterDateFormatTxt.setToolTipText(msg.toString());
				} else {
					configuration.setFilterDateFormat("");
				}
			}
        });

        filterDateTypeLbl = new JLabel(FILTER_DATE_TYPE_LBL);
        filterDateTypeExifBtn = new JRadioButton(FILTER_DATE_TYPE_EXIF_LBL);
        filterDateTypeExifBtn.setToolTipText(FILTER_DATE_TYPE_EXIF_TOOLTIP);
        filterDateTypeExifBtn.addActionListener(new ActionListener() {
			public void actionPerformed(final ActionEvent e) {
				configuration.setFilterDateType(FilterDateType.EXIF);
			}
        });
        filterDateTypeLastModBtn = new JRadioButton(FILTER_DATE_TYPE_LASTMOD_LBL);
        filterDateTypeLastModBtn.setToolTipText(FILTER_DATE_TYPE_LASTMOD_TOOLTIP);
        filterDateTypeLastModBtn.addActionListener(new ActionListener() {
			public void actionPerformed(final ActionEvent e) {
				configuration.setFilterDateType(FilterDateType.LAST_MOD);
			}
        });
        final ButtonGroup filterDateTypeGroup = new ButtonGroup();
        filterDateTypeGroup.add(filterDateTypeExifBtn);
        filterDateTypeGroup.add(filterDateTypeLastModBtn);

        patternTypeLbl = new JLabel(PATTERN_TYPE_LBL);

        patternTypeKeywordsBtn = new JRadioButton(PATTERN_TYPE_KEYWORDS_LBL);
        patternTypeKeywordsBtn.addActionListener(new ActionListener() {
			public void actionPerformed(final ActionEvent e) {
				configuration.setPatternType(PatternType.KEYWORDS);
				setPatternExpressionVisible(PatternType.KEYWORDS);
			}
        });
        patternTypeJsBtn = new JRadioButton(PATTERN_TYPE_JS_LBL);
        patternTypeJsBtn.setToolTipText(PATTERN_TYPE_JS_TOOLTIP);
        patternTypeJsBtn.addActionListener(new ActionListener() {
			public void actionPerformed(final ActionEvent e) {
				configuration.setPatternType(PatternType.JS);
				setPatternExpressionVisible(PatternType.JS);
			}
        });
        final ButtonGroup patternGroup = new ButtonGroup();
        patternGroup.add(patternTypeKeywordsBtn);
        patternGroup.add(patternTypeJsBtn);

        patternExpressionKeywordsLbl = new JLabel(PATTERN_EXPRESSION_KEYWORDS_LBL);
        patternExpressionKeywordsTxt = new JTextField();
        final StringBuilder tooltip = new StringBuilder(PATTERN_EXPRESSION_KEYWORDS_TOOLTIP_START);
        tooltip.append(PATTERN_EXPRESSION_KEYWORDS_TOOLTIP_TABLE_OPEN);
        final Map<SupportedPatternElement, String> keys = KeywordsPattern.getSupportedKeywords();
        for (final SupportedPatternElement key : keys.keySet()) {
        	tooltip.append(PATTERN_EXPRESSION_KEYWORDS_TOOLTIP_ROW_OPEN);
        	tooltip.append(KeywordsPattern.keywordDelimiterForHtml).append(key).append(KeywordsPattern.keywordDelimiterForHtml);
        	tooltip.append(PATTERN_EXPRESSION_KEYWORDS_TOOLTIP_ROW_BETWEEN_CELLS);
        	tooltip.append(keys.get(key));
        	tooltip.append(PATTERN_EXPRESSION_KEYWORDS_TOOLTIP_ROW_CLOSE);
        }
        tooltip.append(PATTERN_EXPRESSION_KEYWORDS_TOOLTIP_TABLE_CLOSE);
        tooltip.append(PATTERN_EXPRESSION_KEYWORDS_TOOLTIP_END);
        patternExpressionKeywordsTxt.setToolTipText(tooltip.toString().replace(File.separator, "&#47;"));
        patternExpressionKeywordsTxt.addFocusListener(new FocusAdapter() {
			@Override
			public void focusLost(final FocusEvent arg0) {
				// Validation du pattern
				final String patternExpressionKeywords = StringUtils.trimToEmpty(patternExpressionKeywordsTxt.getText());
				try {
					KeywordsPattern.validatePattern(patternExpressionKeywords);
					configuration.setPatternKeywordsExpression(patternExpressionKeywords);
				} catch (final Exception e) {
					configuration.setPatternKeywordsExpression("");
					final StringBuilder msg = new StringBuilder(PATTERN_EXPRESSION_KEYWORDS_ERR_MSG).append("\n").append(e.getMessage());
					JOptionPane.showMessageDialog(gpsFrame, msg.toString(), PATTERN_EXPRESSION_KEYWORDS_ERR_TITLE, JOptionPane.ERROR_MESSAGE);
				}
			}
        });

        patternExpressionJsLbl = new JLabel(PATTERN_EXPRESSION_JS_LBL);
        patternExpressionJsTxt = new JTextArea();
        patternExpressionJsTxt.setToolTipText(PATTERN_EXPRESSION_JS_TOOLTIP);
        // Rmq : pas de validation du js en onFocusLost : mode avancé
        patternExpressionJsTxt.getDocument().addDocumentListener(new ModifyListener() {
			@Override
			public void modify(final DocumentEvent event) {
				configuration.setPatternJsExpression(StringUtils.trimToEmpty(patternExpressionJsTxt.getText()));
			}
        });
        scrollPane = new JScrollPane(patternExpressionJsTxt);

        rejectProcessLbl = new JLabel(REJ_PROCESS_LBL);

        rejectProcessBtn = new JCheckBox(REJ_PROCESS_BTN_LBL);
        rejectProcessBtn.addItemListener(new ItemListener() {
        	public void itemStateChanged(final ItemEvent e) {
        		if (e.getStateChange() == ItemEvent.SELECTED) {
        			configuration.setRejectProcess(true);
        			activateRejectProcess(true);
        		} else if (e.getStateChange() == ItemEvent.DESELECTED) {
        			configuration.setRejectProcess(false);
        			activateRejectProcess(false);
        		}
			}
        });

        rejectDirLbl = new JLabel(REJ_DIR_LBL);
        rejectDirTxt = new JTextField();
        rejectDirTxt.addFocusListener(new FocusAdapter() {
			@Override
			public void focusLost(final FocusEvent arg0) {
				final String rejectDir = StringUtils.trimToEmpty(rejectDirTxt.getText());
				configuration.setRejectDir(rejectDir);
				// Validation du dossier
				final File dir = new File(rejectDir);
				if (!dir.exists()) {
					JOptionPane.showMessageDialog(gpsFrame, REJ_DIR_ERR_MSG_NOTFOUND, REJ_DIR_ERR_TITLE, JOptionPane.WARNING_MESSAGE);
				}
				else {
					try {
						FileUtils.checkCanWriteDir(dir, false);
					} catch (final Exception e) {
						// Repositionne le curseur sur le prochain dossier de plus haut niveau existant
						final File highestExistingDir = FileUtils.getHighestExistingParentFolder(dir);
						if (highestExistingDir != null) rejectDirTxt.setText(highestExistingDir.getAbsolutePath());
						final StringBuilder msg = new StringBuilder(REJ_DIR_ERR_MSG).append("\n").append(e.getMessage());
						JOptionPane.showMessageDialog(gpsFrame, msg, REJ_DIR_ERR_TITLE, JOptionPane.WARNING_MESSAGE);
					}
				}
			}
        });
        rejectDirTxt.getDocument().addDocumentListener(new ModifyListener() {
			@Override
			public void modify(final DocumentEvent event) {
				configuration.setRejectDir(StringUtils.trimToEmpty(rejectDirTxt.getText()));
			}
        });
        rejectDirBrowseBtn = new JButton(controller.getBrowseAction());
        rejectDirBrowseBtn.putClientProperty(BrowseAction.FIELD_KEY, rejectDirTxt);

        rejectPatternExpressionKeywordsLbl = new JLabel(REJ_PATTERN_EXPRESSION_KEYWORDS_LBL);
        rejectPatternExpressionKeywordsTxt = new JTextField();
        rejectPatternExpressionKeywordsTxt.setToolTipText(tooltip.toString());
        rejectPatternExpressionKeywordsTxt.addFocusListener(new FocusAdapter() {
			@Override
			public void focusLost(final FocusEvent arg0) {
				final String patternExpressionKeywords = StringUtils.trimToEmpty(rejectPatternExpressionKeywordsTxt.getText());
				try {
					KeywordsPattern.validatePattern(patternExpressionKeywords);
					configuration.setRejectPatternKeywordsExpression(patternExpressionKeywords);
				} catch (final Exception e) {
					final StringBuilder msg = new StringBuilder(PATTERN_EXPRESSION_KEYWORDS_ERR_MSG).append("\n").append(e.getMessage());
					configuration.setRejectPatternKeywordsExpression("");
					JOptionPane.showMessageDialog(gpsFrame, msg.toString(), PATTERN_EXPRESSION_KEYWORDS_ERR_TITLE, JOptionPane.ERROR_MESSAGE);
				}
			}
        });
	}

	/**
     * Place les composants dans le panneau.
     */
	private void placeComponents() {
		final GroupLayout layout = new GroupLayout(this);
    	this.setLayout(layout);

    	// Horizontalement
        layout.setHorizontalGroup(
            layout.createParallelGroup()
	            .addGroup(layout.createSequentialGroup()
	                .addGroup(layout.createParallelGroup()
	                    .addComponent(actionLbl)
	                    .addComponent(filterTypeLbl)
	                    .addComponent(filterExtensionLbl)
	                    .addComponent(filterExpressionLbl)
	                    .addComponent(filterByDateLbl)
	                    .addComponent(patternTypeLbl)
	                    .addComponent(patternExpressionKeywordsLbl)
	                    .addComponent(patternExpressionJsLbl)
	                    .addComponent(rejectProcessLbl))
	                .addGroup(layout.createParallelGroup()
	                	.addGroup(layout.createParallelGroup()
		                	.addGroup(layout.createSequentialGroup()
		                		.addComponent(moveBtn)
		                        .addComponent(copyBtn))
		                    .addGroup(layout.createSequentialGroup()
		                    	.addGap(250)
		                        .addComponent(overwriteBtn)
		                        .addPreferredGap(ComponentPlacement.RELATED)
		                        .addGap(15)
		                        .addComponent(recursiveBtn)
		                        .addPreferredGap(ComponentPlacement.RELATED)
		                        .addGap(15)
		                        .addComponent(rotateBtn)))
		                .addGroup(layout.createParallelGroup(Alignment.LEADING)
		                	.addGroup(layout.createSequentialGroup()
		                		.addComponent(filterTypeExtensionBtn)
		                        .addComponent(filterTypeExpressionBtn))
		                    .addGroup(layout.createSequentialGroup()
			                    .addGap(250)
			                    .addComponent(filterShowRejectsBtn)))
	                    .addComponent(filterExtensionTxt)
	                    .addComponent(filterExpressionTxt)
	                	.addGroup(layout.createSequentialGroup()
	                		.addComponent(filterByDateBtn)
	                        .addPreferredGap(ComponentPlacement.RELATED)
	                        .addComponent(filterDateMinLbl)
	                        .addComponent(filterDateMinTxt)
	                        .addPreferredGap(ComponentPlacement.RELATED)
	                        .addComponent(filterDateMaxLbl)
	                        .addComponent(filterDateMaxTxt)
	                        .addPreferredGap(ComponentPlacement.RELATED)
	                        .addComponent(filterDateFormatLbl)
	                        .addComponent(filterDateFormatTxt)
	                        .addPreferredGap(ComponentPlacement.RELATED)
	                        .addComponent(filterDateTypeLbl)
	                        .addComponent(filterDateTypeExifBtn)
	                        .addComponent(filterDateTypeLastModBtn))
	                	.addGroup(layout.createSequentialGroup()
	                		.addComponent(patternTypeKeywordsBtn)
	                        .addPreferredGap(ComponentPlacement.RELATED)
	                        .addComponent(patternTypeJsBtn))
	                    .addComponent(patternExpressionKeywordsTxt)
	                    .addComponent(scrollPane, GroupLayout.DEFAULT_SIZE, TEXT_FIELD_WIDTH, Short.MAX_VALUE)
	                	.addGroup(layout.createSequentialGroup()
	                		.addComponent(rejectProcessBtn)
	                        .addPreferredGap(ComponentPlacement.RELATED)
	                        .addComponent(rejectDirLbl)
	                        .addComponent(rejectDirTxt)
	                        .addPreferredGap(ComponentPlacement.RELATED)
	                        .addComponent(rejectDirBrowseBtn)
	                        .addPreferredGap(ComponentPlacement.RELATED)
	                        .addComponent(rejectPatternExpressionKeywordsLbl)
	                        .addComponent(rejectPatternExpressionKeywordsTxt)))));
        // Verticalement
        layout.setVerticalGroup(
            layout.createParallelGroup()
	            .addGroup(layout.createSequentialGroup()
	                .addGroup(layout.createParallelGroup()
	                    .addComponent(actionLbl)
	                    .addComponent(moveBtn)
	                    .addComponent(copyBtn)
	                    .addComponent(overwriteBtn)
	                    .addComponent(recursiveBtn)
	                    .addComponent(rotateBtn))
	                .addPreferredGap(ComponentPlacement.RELATED)
	                .addGroup(layout.createParallelGroup()
	                    .addComponent(filterTypeLbl)
	                    .addComponent(filterTypeExtensionBtn)
	                    .addComponent(filterTypeExpressionBtn)
	                    .addComponent(filterShowRejectsBtn))
	                .addPreferredGap(ComponentPlacement.RELATED)
	                .addGroup(layout.createParallelGroup(Alignment.BASELINE)
	                    .addComponent(filterExtensionLbl)
	                    .addComponent(filterExtensionTxt))
	                .addGroup(layout.createParallelGroup(Alignment.BASELINE)
	                    .addComponent(filterExpressionLbl)
	                    .addComponent(filterExpressionTxt))
	                .addPreferredGap(ComponentPlacement.RELATED)
	                .addGroup(layout.createParallelGroup(Alignment.BASELINE)
	                    .addComponent(filterByDateLbl)
	                    .addComponent(filterByDateBtn)
	                    .addComponent(filterDateMinLbl)
	                    .addComponent(filterDateMinTxt)
	                    .addComponent(filterDateMaxLbl)
	                    .addComponent(filterDateMaxTxt)
	                    .addComponent(filterDateFormatLbl)
	                    .addComponent(filterDateFormatTxt)
	                    .addComponent(filterDateTypeLbl)
	                    .addComponent(filterDateTypeExifBtn)
	                    .addComponent(filterDateTypeLastModBtn))
	                .addGroup(layout.createParallelGroup()
	                    .addComponent(patternTypeLbl)
	                    .addComponent(patternTypeKeywordsBtn)
	                    .addComponent(patternTypeJsBtn))
	                .addPreferredGap(ComponentPlacement.RELATED)
	                .addGroup(layout.createParallelGroup(Alignment.BASELINE)
	                    .addComponent(patternExpressionKeywordsLbl)
	                    .addComponent(patternExpressionKeywordsTxt))
	                .addPreferredGap(ComponentPlacement.RELATED)
	                .addGroup(layout.createParallelGroup()
	                    .addComponent(patternExpressionJsLbl)
	                    .addComponent(scrollPane, GroupLayout.DEFAULT_SIZE, TEXT_AREA_HEIGHT, Short.MAX_VALUE))
	                .addPreferredGap(ComponentPlacement.RELATED)
	                .addGroup(layout.createParallelGroup(Alignment.BASELINE)
	                    .addComponent(rejectProcessLbl)
	                    .addComponent(rejectProcessBtn)
	                    .addComponent(rejectDirLbl)
	                    .addComponent(rejectDirTxt)
	                    .addComponent(rejectDirBrowseBtn)
	                    .addComponent(rejectPatternExpressionKeywordsLbl)
	                    .addComponent(rejectPatternExpressionKeywordsTxt))
		            .addContainerGap())
        );
    }

	/**
	 * Initialise les valeurs en fonction de la configuration.
	 */
	public void initValues() {
		switch(configuration.getProcessAction()) {
		case COPY:
			copyBtn.setSelected(true);
			break;
		case MOVE:
			moveBtn.setSelected(true);
			break;
		default:
			throw new IllegalArgumentException(MessageFormat.format(UNSUPPORTED_PROCESS_ACTION, configuration.getProcessAction()));
		}
		overwriteBtn.setSelected(configuration.isOverwrite());
		recursiveBtn.setSelected(configuration.isRecursive());
		rotateBtn.setSelected(configuration.isRotate());

		switch(configuration.getFilterType()) {
		case EXTENSION:
			filterTypeExtensionBtn.setSelected(true);
			setFilterVisible(FilterType.EXTENSION);
			break;
		case REGEX:
			filterTypeExpressionBtn.setSelected(true);
			setFilterVisible(FilterType.REGEX);
			break;
		default:
			throw new IllegalArgumentException(MessageFormat.format(UNSUPPORTED_FILTER_TYPE, configuration.getProcessAction()));
		}
		filterExtensionTxt.setText(configuration.getFilterExtension());
		filterExpressionTxt.setText(configuration.getFilterExpression());
		filterShowRejectsBtn.setSelected(configuration.isFilterShowRejects());

		filterByDateBtn.setSelected(configuration.isFilterByDate());
		activateDateFilter(configuration.isFilterByDate());
		filterDateMinTxt.setText(configuration.getFilterDateMin());
		filterDateMaxTxt.setText(configuration.getFilterDateMax());
		filterDateFormatTxt.setText(configuration.getFilterDateFormat());
		switch(configuration.getFilterDateType()) {
		case EXIF:
			filterDateTypeExifBtn.setSelected(true);
			break;
		case LAST_MOD:
			filterDateTypeLastModBtn.setSelected(true);
			break;
		default:
			throw new IllegalArgumentException(MessageFormat.format(UNSUPPORTED_DATEFILTER_TYPE, configuration.getFilterDateType()));
		}

		switch(configuration.getPatternType()) {
		case KEYWORDS:
			patternTypeKeywordsBtn.setSelected(true);
			setPatternExpressionVisible(PatternType.KEYWORDS);
			break;
		case JS:
			patternTypeJsBtn.setSelected(true);
			setPatternExpressionVisible(PatternType.JS);
			break;
		default:
			throw new IllegalArgumentException(MessageFormat.format(UNSUPPORTED_PATTERN_TYPE, configuration.getPatternType()));
		}
		patternExpressionKeywordsTxt.setText(configuration.getPatternKeywordsExpression());
		patternExpressionJsTxt.setText(configuration.getPatternJsExpression());

		rejectProcessBtn.setSelected(configuration.isRejectProcess());
		activateRejectProcess(configuration.isRejectProcess());
		rejectDirTxt.setText(configuration.getRejectDir().getAbsolutePath());
		rejectPatternExpressionKeywordsTxt.setText(configuration.getRejectPatternKeywordsExpression());
	}

	/**
	 * Gère la visibilité des champs de saisie de pattern selon le type de pattern choisi.
	 * @param patternType Le type de pattern.
	 */
	private void setPatternExpressionVisible(final PatternType patternType) {
		if (patternType == PatternType.KEYWORDS) {
			patternExpressionKeywordsLbl.setVisible(true);
			patternExpressionKeywordsTxt.setVisible(true);
			patternExpressionJsLbl.setVisible(false);
			scrollPane.setVisible(false);
		} else if (patternType == PatternType.JS) {
			patternExpressionKeywordsLbl.setVisible(false);
			patternExpressionKeywordsTxt.setVisible(false);
			patternExpressionJsLbl.setVisible(true);
			scrollPane.setVisible(true);
		}
		if (gpsFrame != null) {
			SwingUtils.pack(gpsFrame);
		}
	}

	/**
	 * Gère la visibilité des champs de saisie de filtre selon le type de filtre choisi.
	 * @param filterType Le type de filtre.
	 */
	private void setFilterVisible(final FilterType filterType) {
		if (filterType == FilterType.EXTENSION) {
			filterExtensionLbl.setVisible(true);
			filterExtensionTxt.setVisible(true);
			filterExpressionLbl.setVisible(false);
			filterExpressionTxt.setVisible(false);
		} else if (filterType == FilterType.REGEX) {
			filterExtensionLbl.setVisible(false);
			filterExtensionTxt.setVisible(false);
			filterExpressionLbl.setVisible(true);
			filterExpressionTxt.setVisible(true);
		}
		if (gpsFrame != null) {
			SwingUtils.pack(gpsFrame);
		}
	}

	/**
	 * Gère l'activation des champs de saisie de filtre par date.
	 * @param activate <code>true</code> ou <code>false</code>.
	 */
	private void activateDateFilter(final boolean activate) {
		filterDateMinLbl.setEnabled(activate);
		filterDateMinTxt.setEnabled(activate);
		filterDateMaxLbl.setEnabled(activate);
		filterDateMaxTxt.setEnabled(activate);
		filterDateFormatTxt.setEnabled(activate);
		filterDateTypeLbl.setEnabled(activate);
		filterDateTypeExifBtn.setEnabled(activate);
		filterDateTypeLastModBtn.setEnabled(activate);
	}

	/**
	 * Gère l'action des champs de gestion de rejet.
	 * @param activate <code>true</code> ou <code>false</code>.
	 */
	private void activateRejectProcess(final boolean activate) {
		rejectDirLbl.setEnabled(activate);
		rejectDirTxt.setEnabled(activate);
		if (activate) rejectDirTxt.setEditable(false); // Rmq: pr l'instant on force rejectDir=dstDir
		rejectDirBrowseBtn.setEnabled(false); // Rmq: pr l'instant on force rejectDir=dstDir
		rejectPatternExpressionKeywordsLbl.setEnabled(activate);
		rejectPatternExpressionKeywordsTxt.setEnabled(activate);
	}

	/**
	 * Renvoie le champ de saisie du chemin de base pour les rejets.
	 * @return Le champ de saisie du chemin de base pour les rejets.
	 */
	public JTextField getRejectDirTxt() {
		return rejectDirTxt;
	}
}
